<?php

declare(strict_types=1);

namespace app\sys\controller;

use app\sys\service\SystemMenuService;
use think\admin\Controller;
use think\admin\Exception;
use think\admin\extend\JwtExtend;
use think\admin\model\SysMessage;
use think\admin\model\SysModule;
use think\admin\model\SysFeedback;
use think\admin\model\SysRelation;
use think\admin\model\SysUser;
use think\admin\service\AdminService;
use think\admin\service\CaptchaService;
use think\admin\service\EmailService;
use think\admin\service\SmsService;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;

/**
 * 用户接口
 * @login true
 * Class UserCenter
 * @package app\auth\controller
 */
class UserCenter extends Controller
{
    /**
     * 登录时获取菜单
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function loginMenu()
    {
        $menus = SystemMenuService::instance()->getMenus(SystemMenuService::instance()->getModuleMenus(), SystemMenuService::instance()->getSpaMenus());
        $this->success('获取成功！', $menus);
    }

    /**
     * 获取手机端菜单
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function loginMobileMenu()
    {
        $menus = SystemMenuService::instance()->getMobileModuleMenus();
        $this->success('获取成功！', $menus);
    }

    /**
     * 获取用户扩展信息
     * @return void
     */
    public function getUserExtendData()
    {
        $data = AdminService::getUserData();
        $result = $data ? json_decode(html_entity_decode($data),true) : [];
        $this->success('获取成功',$result);
    }

    /**
     * 获取用户首页快捷菜单
     * @return void
     * @throws Exception
     */
    public function getUserShortcutMenu()
    {
        $data = AdminService::getUserShortcutMenu();
        $result = $data ? json_decode(html_entity_decode($data),true) : [];
        $this->success('获取成功',$result);
    }

    /**
     * 获取用户使用习惯
     * @return void
     * @throws Exception
     */
    public function getUserUsageHabit()
    {
        $data = AdminService::getUserUsageHabit();
        $result = $data != 'default' ? json_decode(html_entity_decode($data)) : [
            'productVal'=> 'SELECT',
            'batchVal'=> 'SELECT',
            'bindingVal'=> 'SE',
            'uselessVal'=> 'SE',
            'codetypeVal'=> [],
            'duration'=> 1000
        ];
        $this->success('获取成功',$result);
    }

    /**
     * 写入用户首页快捷菜单
     * @return void
     * @throws Exception
     */
    public function setUserShortcutMenu()
    {
        $data = $this->_vali([
            'shortcutMenu.require' => '快捷菜单不能为空'
        ]);

        $this->success('配置成功！', AdminService::setUserShortcutMenu($data['shortcutMenu']));
    }

    /**
     * 写入用户使用习惯
     * @return void
     * @throws Exception
     */
    public function setUserUsageHabit()
    {
        $data = $this->_vali([
            'usageHabit.require' => '使用习惯配置不能为空'
        ]);
        $this->success('配置成功！', AdminService::setUserUsageHabit($data['usageHabit']));
    }

    /**
     * 切换商户换取商用所有可使用模块
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function merchantIdToModuleArr()
    {
        $data = $this->_vali([
            'merchantId.require' => '商户标识不能为空'
        ]);
        $this->success('配置成功！', AdminService::getMerchantModule(AdminService::getMerchantDetail($data['merchantId'])));
    }

    /**
     * 提交反馈
     * @return void
     */
    public function userFeedback()
    {
        SysFeedback::mForm();
    }

    /**
     * 我的快捷菜单
     * @login true
     * @return void
     */
    public function loginWorkbench()
    {
        $this->success('快捷菜单获取成功！', AdminService::getUser()['extJson']);
    }

    /**
     * 更新模块ID
     * @return void
     */
    public function getModuleId()
    {
        $this->success('获取成功！', AdminService::getModuleId($this->request->param('merchantId')));
    }


    /**
     * 我的未读站内信
     * @login true
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function loginUnreadMessagePage()
    {
        $ids = SysRelation::mk()->where(['target_id' => AdminService::getUserId()])->where(['category' => 'DEV_MESSAGE_HAS_USER'])->column('object_id');
        $query = SysMessage::mQuery();
        $query->whereIn('id', $ids);
        // 数据列表搜索过滤
        $query->equal('status');
        $query->like('category');
        $lists = $query->order('id ASC')->page();
        sysoplog('用户消息管理', '用户消息分页列表获取成功');
        $this->success('数据获取成功', $lists['list']);
    }

    /**
     * 登录获取我的消息详情
     * @login true
     * @return void
     * @throws DbException
     */
    public function loginUnreadMessageDetail()
    {
        $detail = SysMessage::mk()->where(['id' => $this->request->param('id')])->where(['is_deleted' => 0, 'status' => 0])->findOrEmpty();
        $json = [
            'read' => true,
            'readTime' => date('Y-m-d h:i:s', time())
        ];
        if (!$detail->isEmpty()) {
            SysRelation::mk()
                ->where(['target_id' => AdminService::getUserId()])
                ->where(['category' => 'DEV_MESSAGE_HAS_USER'])
                ->where(['object_id' => $this->request->param('id')])
                ->update(['ext_json' => json_encode($json)]);
        }
        /*
        $receiveInfoList = [];
        $receiveList = SysRelation::mk()->where(['object_id'=>$this->request->param('id')])->where(['category'=>'DEV_MESSAGE_HAS_USER'])->select()->toArray();
        if($receiveList){
            foreach($receiveList as $v){
                $receiveInfoList[] = [
                    'receiveUserId' => $v['targetId'],
                    'receiveUserName' => $this->_getUserName((int)$v['targetId']),
                    'read' => json_decode($v['extJson'],true)['read']
                ];
            }
        }
        $detail['receiveInfoList'] = $receiveInfoList;
        */
        $this->success('获取成功', $detail);
    }

    /**
     * 获取图形验证码
     * @return void
     */
    public function getPicCaptcha()
    {
        $image = CaptchaService::instance()->initialize();
        $captcha = ['image' => $image->getData(), 'uniqid' => $image->getUniqid()];
        $this->success('生成验证码成功', $captcha);
    }

    /**
     * 找回密码图形验证通过后发短信
     * @return void
     * @throws Exception
     */
    public function findPasswordGetPhoneValidCode()
    {
        $data = $this->_vali([
            'phone.mobile' => '手机号格式错误！',
            'phone.require' => '手机号不能为空！',
            'verify.require' => '图形验证码不能为空!',
            'uniqid.require' => '图形验证标识不能为空!',
            'action.require' => '请求方法不能为空'
        ]);
        if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) {
            $this->error('图形验证码验证失败，请重新输入!');
        }
        $map = ['phone' => $data['phone'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        if ($data['action'] !== null) {
            if ($user->isEmpty() && in_array($data['action'], ['login', 'recover'], true)) {
                $this->error('手机号不存在!');
            }
            if (!$user->isEmpty() && $data['action'] === 'register') {
                $this->error('手机号已被注册!');
            }
            if (!in_array($data['action'], ['login', 'recover', 'register'], true)) {
                $this->error('未知请求来源!');
            }
        } else {
            $this->error('未知错误!');
        }
        [$state, $message, $data] = SmsService::instance()->sendVerifyCode($data['phone']);
        $state ? $this->success($message, $data) : $this->error($message, $data);
    }

    /**
     * 找回密码图形验证通过后发邮件
     * @return void
     * @throws Exception
     */
    public function findPasswordGetEmailValidCode()
    {
        $data = $this->_vali([
            'email.email' => '邮箱格式错误！',
            'email.require' => '邮箱不能为空！',
            'verify.require' => '图形验证码不能为空!',
            'uniqid.require' => '图形验证标识不能为空!',
            'action.require' => '请求方法不能为空'
        ]);
        if (!CaptchaService::instance()->check($data['verify'], $data['uniqid'])) {
            $this->error('图形验证码验证失败，请重新输入!');
        }
        $map = ['email' => $data['email'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        if ($data['action'] !== null) {
            if ($user->isEmpty() && in_array($data['action'], ['login', 'recover'], true)) {
                $this->error('邮箱不存在!');
            }
            if (!$user->isEmpty() && $data['action'] === 'register') {
                $this->error('邮箱已被注册!');
            }
            if (!in_array($data['action'], ['login', 'recover', 'register'], true)) {
                $this->error('未知请求来源!');
            }
        } else {
            $this->error('未知错误!');
        }
        [$state, $message, $data] = EmailService::instance()->sendVerifyCode($data['email']);
        $state ? $this->success($message, $data) : $this->error($message, $data);
    }

    /**
     * 手机号找回密码
     * @return void
     * @throws Exception
     */
    public function findPasswordByPhone()
    {
        $data = $this->_vali([
            'phone.mobile' => '手机号格式错误！',
            'phone.require' => '手机号不能为空！',
            'captcha.require' => '验证码不能为空!',
            'newPassword.require' => '新密码不能为空!'
        ]);
        if (!SmsService::instance()->checkVerifyCode($data['captcha'], $data['phone'])) {
            $this->error('手机短信验证失败！');
        }
        $map = ['phone' => $data['phone'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        $this->newPasswordWrite($user, $data);
    }

    /**
     * 新密码写入
     * @param $user
     * @param array $data
     * @return void
     */
    public function newPasswordWrite($user, array $data): void
    {
        if ($user->isEmpty()) {
            $this->app->session->set('restPasswordInputSessionError', true);
            $this->error('登录错误，请重重试!');
        }
        if ($user['password'] === $data['newPassword']) {
            $this->app->session->set('restPasswordInputSessionError', true);
            $this->error('新密码与原密码相同，无需重置。');
        }
        $data['password'] = trim($data['newPassword']);
        $data['id'] = $user['id'];
        unset($data['newPassword']);
        unset($data['captcha']);
        $this->app->session->delete('restPasswordInputSessionError');
        SysUser::mSave($data);
    }

    /**
     * 邮箱找回密码
     * @return void
     * @throws Exception
     */
    public function findPasswordByEmail()
    {
        $data = $this->_vali([
            'email.email' => '邮箱格式错误！',
            'email.require' => '邮箱不能为空！',
            'captcha.require' => '验证码不能为空!',
            'newPassword.require' => '新密码不能为空!'
        ]);
        if (!EmailService::instance()->checkVerifyCode($data['captcha'], $data['email'])) {
            $this->error('邮箱验证失败！');
        }
        $map = ['email' => $data['email'], 'is_deleted' => 0];
        $user = SysUser::mk()->where($map)->findOrEmpty();
        $this->newPasswordWrite($user, $data);
    }

    /**
     * 刷新TOKEN
     * @return string
     * @throws Exception
     */
    public function refreshToken(): string
    {
        return JwtExtend::getNewToken($this->request->post('refreshToken'));
    }

    /**
     * 我的消息列表数据处理
     * @param array $data
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    protected function _page_filter(array &$data)
    {
        $messages = SysRelation::mk()->where(['target_id' => AdminService::getUserId()])->where(['category' => 'DEV_MESSAGE_HAS_USER'])->select()->toArray();
        foreach ($data as &$v) {
            foreach ($messages as $msg) {
                if ($msg['objectId'] === (string)$v['id']) {
                    $v['read'] = json_decode($msg['extJson'], true)['read'];
                }
            }
        }
    }

    /**
     * 获取用户名
     * @param int $id
     * @return string
     */
    private function _getUserName(int $id): string
    {
        return SysUser::mk()->where(['id' => $id])->value('name');
    }

    /**
     * 显示完整信息
     * @return void
     */
    public function userFullData()
    {
        $data = $this->_vali([
            'id.require' => 'id不能为空！',
            'field.require' => '字段不能为空!'
        ]);
        $user = SysUser::mk()->where(['id'=>$data['id']])->findOrEmpty();
        if($data['field'] === 'phone'){
            $dat = $user->full_phone;
        }else{
            $dat = $user->full_email;
        }
        $this->success('获取成功', $dat);
    }

    /**
     * 更新个人信息
     * @return void
     */
    public function upDateInfo()
    {
        SysUser::mForm('form');
    }

    /**
     * 更新用户资料
     * @return void
     */
    public function updateUserInfo()
    {
        SysUser::mForm();
    }

    /**
     * 修改密码(手机APP)
     * @return void
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function modifyPassword()
    {

        $data = $this->_vali([
            'id.require' => '用户ID不能为空！',
            'oldPassword.require' => '登录密码不能为空！',
            'newPassword.require' => '重复密码不能为空！',
            'newPassword_confirmation.confirm:newPassword' => '两次输入的密码不一致！',
            'uniqid.require' => '验证标识不能为空!'
        ]);
        $user = SysUser::mk()->where(['id'=>$data['id']])->findOrEmpty();
        if($user->isEmpty()){
            $this->error('用户不存在!');
        }
        if (md5("{$user['password']}{$data['uniqid']}") != $data['oldPassword']) {
            sysoplog('密码修改', '旧密码错误');
            $this->error('密码错误，请重新输入!');
        }
        if ($user->save(['password' => $data['newPassword']])) {
            sysoplog('系统用户管理', "修改用户{$data['id']}密码成功");
            $this->success('密码修改成功，请使用新密码登录！', '');
        } else {
            $this->error('密码修改失败，请稍候再试！');
        }
    }

    /**
     * 更新密码
     * @return void
     */
    public function updatePassword()
    {
        $data = $this->_vali([
            'id.require' => 'id不能为空！',
            'password.require' => '旧密码不能为空!',
            'newPassword.require' => '新密码不能为空!',
            'newPassword.min:8' => '新密码不能少于8位!',
            'checkPassword.require' => '确认密码不能为空!'
        ]);
        if($data['newPassword'] !== $data['checkPassword']) $this->error('二次输入的新密码不相同');
        $user = SysUser::mk()->where(['id' => $data['id']])->where(['is_deleted' => 0])->findOrEmpty();
        if(!$user->isEmpty()){
            if($user->password === $data['password']){
                if($user->password === $data['newPassword']) $this->error('新密码与旧密码不能相同');
                if(SysUser::mk()->where(['id'=>$data['id']])->update(['password'=>$data['newPassword']])){
                    $this->success('密码更新成功');
                }else{
                    $this->error('密码更新失败');
                }
            }else{
                $this->error('旧密码错误');
            }
        }else{
            $this->error('用户不存在');
        }
    }



    /**
     * 修改邮箱
     * @return void
     * @throws Exception
     */
    public function updateEmail()
    {
        $data = $this->_vali([
            'id.require' => '用户ID不能为空',
            'password.require' => '登录密码不能为空!',
            'email.email' => '邮箱格式错误！',
            'email.require' => '手机不能为空！',
            'captcha.require' => '验证码不能为空！'
        ]);
        if (!EmailService::instance()->checkVerifyCode($data['captcha'], $data['email'])) {
            $this->error('邮件验证码验证失败！');
        }
        $user = SysUser::mk()->where(['id' => $data['id']])->where(['is_deleted' => 0])->findOrEmpty();
        $userCheck = SysUser::mk()->where('id', '<>', $data['id'])->where(['email' => $data['email']])->where(['is_deleted' => 0])->findOrEmpty();
        if (!$userCheck->isEmpty()) {
            sysoplog('修改邮箱', '邮箱已存在');
            $this->error('邮箱已存在!');
        }
        if ($user->isEmpty()) {
            sysoplog('修改邮箱', '用户账号不存在');
            $this->error('账号错误，请联系平台客服!');
        }
        if (md5("{$user['password']}") != $data['password']) {
            sysoplog('修改邮箱', '用户密码错误');
            $this->error('密码错误，请重新输入!');
        }
        if ($user['email'] === $data['email']) {
            sysoplog('修改邮箱', '原手机号与新手机号相同');
            $this->error('原邮箱与新邮箱相同，请重新输入!');
        } else {
            if (SysUser::mk()->where(['id' => $data['id']])->update(['email' => $data['email']])) {
                sysoplog('修改邮箱', '邮箱修改成功');
                $this->success('邮箱修改成功，以后请用新邮箱登录！');
            } else {
                sysoplog('修改邮箱', '邮箱修改失败');
                $this->error('邮箱修改失败！');
            }
        }
    }

    /**
     * 修改手机号
     * @return void
     * @throws Exception
     */
    public function updatePhone()
    {
        $data = $this->_vali([
            'id.require' => '用户ID不能为空',
            'password.require' => '登录密码不能为空!',
            'phone.mobile' => '手机格式错误！',
            'phone.require' => '手机不能为空！',
            'captcha.require' => '验证码不能为空！'
        ]);
        if (!SmsService::instance()->checkVerifyCode($data['captcha'], $data['phone'])) {
            $this->error('手机短信验证失败！');
        }
        $user = SysUser::mk()->where(['id' => $data['id']])->where(['is_deleted' => 0])->findOrEmpty();
        $userCheck = SysUser::mk()->where('id', '<>', $data['id'])->where(['phone' => $data['phone']])->where(['is_deleted' => 0])->findOrEmpty();
        if (!$userCheck->isEmpty()) {
            sysoplog('修改手机号', '手机号已存在');
            $this->error('手机号已存在!');
        }
        if ($user->isEmpty()) {
            sysoplog( '修改手机号', '用户账号不存在');
            $this->error('账号错误，请联系平台客服!');
        }
        if (md5("{$user['password']}") != $data['password']) {
            sysoplog('修改手机号', '用户密码错误');
            $this->error('密码错误，请重新输入!');
        }
        if ($user['contact_phone'] === $data['phone']) {
            sysoplog( '修改手机号', '原手机号与新手机号相同');
            $this->error('原手机号与新手机号相同，请重新输入!');
        } else {
            if (SysUser::mk()->where(['id' => $data['id']])->update(['phone' => $data['phone']])) {
                sysoplog('修改手机号', '手机号修改成功');
                $this->success('手机号修改成功，以后请用新手机号登录！');
            } else {
                sysoplog('修改手机号', '手机号修改失败');
                $this->error('手机号修改失败！');
            }
        }

    }
}